package com.example.personalizededucationsystem.service;

import com.example.personalizededucationsystem.dto.dto.GradeSubmissionRequestDto;
import com.example.personalizededucationsystem.dto.dto.StudentAnswerDetailDto;
import com.example.personalizededucationsystem.dto.dto.TeacherAssignmentDto;
import com.example.personalizededucationsystem.dto.request.AssignmentSubmissionRequest;
import com.example.personalizededucationsystem.dto.request.CreateAssignmentRequest;
import com.example.personalizededucationsystem.dto.response.AssignmentResponse;
import com.example.personalizededucationsystem.model.*;
import com.example.personalizededucationsystem.model.Class;
import com.example.personalizededucationsystem.repository.*;
import jakarta.persistence.EntityNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
public class AssignmentService {
    private final AssignmentRepository assignmentRepository;
    private final ClassRepository classRepository;
    private final QuestionRepository questionRepository;
    private final ClassMemberRepository classMemberRepository;
    private final UserRepository userRepository;
    private final StudentAssignmentRepository studentAssignmentRepository;
    private final StudentAssignmentAnswerRepository studentAssignmentAnswerRepository;

    @Autowired
    public AssignmentService(AssignmentRepository assignmentRepository, ClassRepository classRepository, QuestionRepository questionRepository, ClassMemberRepository classMemberRepository, UserRepository userRepository, StudentAssignmentRepository studentAssignmentRepository, StudentAssignmentAnswerRepository studentAssignmentAnswerRepository) {
        this.assignmentRepository = assignmentRepository;
        this.classRepository = classRepository;
        this.questionRepository = questionRepository;
        this.classMemberRepository = classMemberRepository;
        this.userRepository = userRepository;
        this.studentAssignmentRepository = studentAssignmentRepository;
        this.studentAssignmentAnswerRepository = studentAssignmentAnswerRepository;
    }

    @Transactional
    public Assignment createAssignment(CreateAssignmentRequest request, User teacher) {
        Class aClass = classRepository.findById(request.getClassId())
                .orElseThrow(() -> new EntityNotFoundException("班级未找到"));
        if (!aClass.getTeacher().getUserId().equals(teacher.getUserId())) {
            throw new AccessDeniedException("您无权为该班级布置作业");
        }

        Assignment assignment = new Assignment();
        assignment.setTitle(request.getTitle());
        assignment.setDescription(request.getDescription());
        assignment.setDeadline(request.getDeadline());
        assignment.setMyClass(aClass);
        assignment.setTeacher(teacher);
        Assignment savedAssignment = assignmentRepository.save(assignment);

        List<Question> questions = questionRepository.findAllById(request.getQuestionIds());
        AtomicInteger order = new AtomicInteger(0);
        questions.forEach(q -> {
            AssignmentQuestion aq = new AssignmentQuestion();
            aq.setAssignment(savedAssignment);
            aq.setQuestion(q);
            aq.setQuestionOrder(order.incrementAndGet());
            savedAssignment.getAssignmentQuestions().add(aq);
        });

        List<ClassMember> members = classMemberRepository.findByMyClass(aClass);
        members.forEach(member -> {
            StudentAssignment sa = new StudentAssignment();
            sa.setStudent(member.getStudent());
            sa.setAssignment(savedAssignment);
            sa.setStatus(StudentAssignment.Status.NOT_STARTED);
            studentAssignmentRepository.save(sa);
        });

        return savedAssignment;
    }

    @Transactional
    public void submitAssignment(Long assignmentId, AssignmentSubmissionRequest request, User student) {
        Assignment assignment = assignmentRepository.findById(assignmentId)
                .orElseThrow(() -> new EntityNotFoundException("作业未找到"));

        StudentAssignment studentAssignment = studentAssignmentRepository.findByStudentAndAssignment(student, assignment)
                .orElseThrow(() -> new AccessDeniedException("您没有这项作业"));

        if (studentAssignment.getStatus() == StudentAssignment.Status.SUBMITTED || studentAssignment.getStatus() == StudentAssignment.Status.GRADED) {
            throw new IllegalStateException("您已提交过此作业");
        }
        if (Instant.now().isAfter(assignment.getDeadline())) {
            throw new IllegalStateException("已超过作业截止日期");
        }

        request.getAnswers().forEach(answerDto -> {
            Question question = questionRepository.findById(answerDto.getQuestionId())
                    .orElseThrow(() -> new EntityNotFoundException("作业中的题目ID " + answerDto.getQuestionId() + " 无效"));

            StudentAssignmentAnswer answer = new StudentAssignmentAnswer();
            answer.setStudentAssignment(studentAssignment);
            answer.setQuestion(question);

            String rawAnswer = answerDto.getUserAnswer();
            String filteredAnswer = rawAnswer;

            Question.QuestionType type = question.getType();
            boolean correct = false;

            if (type == Question.QuestionType.SINGLE_CHOICE || type == Question.QuestionType.MULTIPLE_CHOICE) {
                filteredAnswer = filterAndSortAnswers(rawAnswer);
                String correctAnswer = filterAndSortAnswers(question.getAnswer());
                answer.setUserAnswer(filteredAnswer);
                correct = filteredAnswer.equals(correctAnswer);
            } else {
                answer.setUserAnswer(rawAnswer);
            }

            answer.setIsCorrect(correct);
            studentAssignmentAnswerRepository.save(answer);
        });

        studentAssignment.setStatus(StudentAssignment.Status.SUBMITTED);
        studentAssignment.setSubmissionDate(Instant.now());
        studentAssignmentRepository.save(studentAssignment);
    }

    private String filterAndSortAnswers(String input) {
        if (input == null) return "";
        String filtered = input.replaceAll("[^A-D]", "");
        char[] chars = filtered.toCharArray();
        java.util.Arrays.sort(chars);
        return new String(chars);
    }

    public List<StudentAnswerDetailDto> getSubmissionDetail(Long assignmentId, Long studentId, User teacher) {
        Assignment assignment = assignmentRepository.findById(assignmentId).orElseThrow(() -> new EntityNotFoundException("作业未找到"));
        User student = userRepository.findById(studentId).orElseThrow(() -> new EntityNotFoundException("学生未找到"));
        StudentAssignment studentAssignment = studentAssignmentRepository.findByStudentAndAssignment(student, assignment).orElseThrow(() -> new EntityNotFoundException("未找到该学生的提交记录"));
        List<StudentAssignmentAnswer> answers = studentAssignmentAnswerRepository.findByStudentAssignment(studentAssignment);
        return answers.stream()
                .map(StudentAnswerDetailDto::from)
                .collect(Collectors.toList());
    }

    public List<StudentAssignment> getSubmissionsForAssignment(Long assignmentId, User teacher) {
        Assignment assignment = assignmentRepository.findById(assignmentId)
                .orElseThrow(() -> new EntityNotFoundException("作业未找到"));

        if (!assignment.getTeacher().getUserId().equals(teacher.getUserId())) {
            throw new AccessDeniedException("您无权查看此作业的提交情况");
        }

        return studentAssignmentRepository.findByAssignmentIdWithStudent(assignmentId);
    }

    public List<TeacherAssignmentDto> getAssignmentsByClass(Long classId, User user) {
        List<Assignment> assignments = assignmentRepository.findByMyClass_ClassId(classId);
        return assignments.stream()
                .map(TeacherAssignmentDto::fromEntity)
                .collect(Collectors.toList());
    }

    @Transactional
    public void gradeSubmission(Long studentAssignmentId, GradeSubmissionRequestDto request, User teacher) {
        StudentAssignment studentAssignment = studentAssignmentRepository.findById(studentAssignmentId)
                .orElseThrow(() -> new EntityNotFoundException("学生作业提交记录未找到"));

        Assignment assignment = studentAssignment.getAssignment();
        if (!assignment.getTeacher().getUserId().equals(teacher.getUserId())) {
            throw new AccessDeniedException("您无权批改此作业");
        }

        if (studentAssignment.getStatus() != StudentAssignment.Status.SUBMITTED) {
            throw new IllegalStateException("该作业尚未提交或已被批改");
        }

        studentAssignment.setScore(request.getScore());
        studentAssignment.setStatus(StudentAssignment.Status.GRADED);
        studentAssignmentRepository.save(studentAssignment);
    }

    public List<StudentAssignment> getAssignmentsForStudent(User student) {
        return studentAssignmentRepository.findByStudentWithDetails(student);
    }

    public AssignmentResponse getAssignmentById(Long assignmentId) {
        Assignment assignment = assignmentRepository.findById(assignmentId)
                .orElseThrow(() -> new EntityNotFoundException("作业未找到"));
        return AssignmentResponse.fromEntity(assignment);
    }

    public List<AssignmentResponse> getAssignmentByClass(Long classId) {
        List<Assignment> assignments = assignmentRepository.findByMyClass_ClassId(classId);
        return assignments.stream()
                .map(AssignmentResponse::fromEntity)
                .toList();
    }
}